import { Op } from 'sequelize';
import Dept from '@/models/system/dept.model';
import Role from '@/models/system/role.model';
import User from '@/models/system/user.model';
import RoleDept from '@/models/system/roleDept.model';
import { getLogger } from '@/utils/logger';

const logger = getLogger("dept-service", {
  console: false,
});
const consoleLogger = getLogger("dept-service");

// 树形选择结构
interface TreeSelect {
  id: number;
  label: string;
  children?: TreeSelect[];
}

class DeptService {
  /**
   * 查询部门列表
   * @param params 查询条件
   */
  async selectDeptList(params: any) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`查询部门列表: ${JSON.stringify(params)}`);
      
      const { deptName, status, parentId } = params;
      
      const where: any = { delFlag: '0' };
      
      if (deptName) {
        where.deptName = { [Op.like]: `%${deptName}%` };
      }
      
      if (status) {
        where.status = status;
      }
      
      if (parentId) {
        where.parentId = parentId;
      }
      
      // 查询部门数据
      const depts = await Dept.findAll({
        where,
        order: [
          ['parentId', 'ASC'],
          ['orderNum', 'ASC']
        ]
      });
      
      // 记录查询结果
      logger.info(`部门列表查询完成: 总数=${depts.length}`);
      
      // 转换为普通对象
      return depts.map(dept => dept.toJSON());
    } catch (error) {
      consoleLogger.error(`查询部门列表失败: ${error instanceof Error ? error.message : String(error)}`);
      // 出错时返回空数组而不是抛出异常
      return [];
    }
  }
  
  /**
   * 构建前端所需的树结构
   * @param depts 部门列表
   */
  buildDeptTree(depts: any[]): any[] {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`构建部门树: 部门数量=${depts?.length || 0}`);
      
      // 部门列表为空时返回空数组
      if (!depts || depts.length === 0) {
        logger.warn("构建部门树：提供的部门列表为空");
        return [];
      }

      const returnList: any[] = [];
      const tempList = depts.map(dept => dept.deptId);
      
      for (const dept of depts) {
        // 如果是顶级节点，遍历该父节点的所有子节点
        if (!tempList.includes(dept.parentId)) {
          this.recursionFn(depts, dept);
          returnList.push(dept);
        }
      }
      
      if (returnList.length === 0) {
        logger.info("未找到顶级部门节点，返回原始列表");
        return depts;
      }
      
      // 记录构建结果
      logger.info(`部门树构建完成: 根部门数量=${returnList.length}, 总部门数量=${depts.length}`);
      
      return returnList;
    } catch (error) {
      consoleLogger.error(`构建部门树失败: ${error instanceof Error ? error.message : String(error)}`);
      return [];
    }
  }
  
  /**
   * 递归处理树结构
   * @param list 部门列表
   * @param dept 当前部门
   */
  private recursionFn(list: any[], dept: any) {
    try {
      logger.debug(`递归处理部门树: 当前部门ID=${dept.deptId}, 部门名=${dept.deptName}`);
      
      // 得到子节点列表
      const children: any[] = list.filter(d => d.parentId === dept.deptId);
      
      if (children.length > 0) {
        dept.children = children;
        // 递归获取子节点的子节点
        for (const child of children) {
          this.recursionFn(list, child);
        }
      } else {
        dept.children = [];
      }
    } catch (error) {
      consoleLogger.error(`递归处理部门树失败: ${error instanceof Error ? error.message : String(error)}`);
      dept.children = [];
    }
  }
  
  /**
   * 构建前端所需下拉树结构
   * @param depts 部门列表
   */
  buildDeptTreeSelect(depts: any[]): TreeSelect[] {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`构建部门下拉树: 部门数量=${depts?.length || 0}`);
      
      // 部门列表为空时返回空数组
      if (!depts || depts.length === 0) {
        logger.warn("构建部门下拉树：提供的部门列表为空");
        return [];
      }

      const deptTree = this.buildDeptTree(depts);
      const result = this.convertDeptTreeToSelect(deptTree);
      
      // 记录构建结果
      logger.info(`部门下拉树构建完成: 树节点数量=${result.length}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`构建部门下拉树失败: ${error instanceof Error ? error.message : String(error)}`);
      return [];
    }
  }
  
  /**
   * 将部门树转换为下拉选择结构
   * @param deptTree 部门树
   */
  private convertDeptTreeToSelect(deptTree: any[]): TreeSelect[] {
    try {
      logger.debug(`转换部门树为下拉树: 部门树节点数量=${deptTree?.length || 0}`);
      
      if (!deptTree || deptTree.length === 0) {
        return [];
      }

      return deptTree.map(dept => {
        const treeSelect: TreeSelect = {
          id: dept.deptId,
          label: dept.deptName
        };
        
        if (dept.children && dept.children.length > 0) {
          treeSelect.children = this.convertDeptTreeToSelect(dept.children);
        }
        
        return treeSelect;
      });
    } catch (error) {
      consoleLogger.error(`转换部门树为下拉树失败: ${error instanceof Error ? error.message : String(error)}`);
      return [];
    }
  }
  
  /**
   * 查询部门树结构信息
   * @param params 查询条件
   */
  async selectDeptTreeList(params: any) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`查询部门树结构: ${JSON.stringify(params)}`);
      
      // 查询部门列表
      const depts = await this.selectDeptList(params);
      
      // 记录部门列表查询结果
      logger.debug(`部门列表查询结果: ${depts.length} 条记录`);
      
      // 构建部门树
      const result = this.buildDeptTreeSelect(depts || []);
      
      // 记录部门树构建结果
      logger.info(`部门树结构查询完成: ${result.length} 个顶级节点`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`查询部门树结构失败: ${error instanceof Error ? error.message : String(error)}`);
      return [];
    }
  }
  
  /**
   * 获取部门的父部门名称
   * @param deptId 部门ID
   * @returns 父部门名称
   */
  async getParentDeptName(deptId: number): Promise<string | undefined> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`获取父部门名称: deptId=${deptId}`);
      
      const dept = await Dept.findByPk(deptId);
      if (!dept || !dept.parentId || dept.parentId === 0) {
        logger.info(`部门 ${deptId} 没有父部门`);
        return undefined;
      }
      
      const parentDept = await Dept.findByPk(dept.parentId);
      const parentName = parentDept ? parentDept.deptName : undefined;
      
      // 记录查询结果
      logger.info(`获取父部门名称成功: deptId=${deptId}, parentId=${dept.parentId}, parentName=${parentName}`);
      
      return parentName;
    } catch (error) {
      consoleLogger.error(`获取父部门名称失败: ${error instanceof Error ? error.message : String(error)}`);
      return undefined;
    }
  }
  
  /**
   * 根据角色ID查询部门树信息
   * @param roleId 角色ID
   */
  async selectDeptListByRoleId(roleId: number, deptCheckStrictly: boolean) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据角色ID查询部门树: roleId=${roleId}, deptCheckStrictly=${deptCheckStrictly}`);
      
      // 查询角色对应的部门
      const role = await Role.findByPk(roleId, {
        include: [
          {
            model: Dept,
            through: { attributes: [] },
            where: { delFlag: '0' }
          }
        ]
      });
      
      if (!role) {
        logger.info(`未找到角色: roleId=${roleId}`);
        return [];
      }
      
      const roleDepts = role.get('Depts') as Dept[];
      const deptIds: number[] = roleDepts.map(dept => dept.deptId);
      
      // 如果角色没有关联部门，则返回空列表
      if (deptIds.length === 0) {
        logger.info(`角色没有关联部门: roleId=${roleId}`);
        return [];
      }
      
      // 非严格模式时，需要查询关联部门的父部门ID
      if (!deptCheckStrictly) {
        for (const deptId of [...deptIds]) {
          const dept = await Dept.findByPk(deptId);
          if (dept && dept.ancestors) {
            const parentIds = dept.getAncestorsArray();
            deptIds.push(...parentIds);
          }
        }
      }
      
      const uniqueDeptIds = [...new Set(deptIds)]; // 去重
      
      // 记录查询结果
      logger.info(`角色部门查询完成: roleId=${roleId}, 部门数量=${uniqueDeptIds.length}, 严格模式=${deptCheckStrictly}`);
      
      return uniqueDeptIds;
    } catch (error) {
      consoleLogger.error(`根据角色ID查询部门树信息失败: ${error instanceof Error ? error.message : String(error)}`);
      return [];
    }
  }
  
  /**
   * 根据部门ID查询信息
   * @param deptId 部门ID
   */
  async selectDeptById(deptId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据ID查询部门: deptId=${deptId}`);
      
      const dept = await Dept.findByPk(deptId);
      if (!dept) {
        logger.info(`未找到部门: deptId=${deptId}`);
        return null;
      }
      
      // 获取父部门名称
      const parentName = dept.parentId ? await this.getParentDeptName(deptId) : undefined;
      
      // 转换为普通对象并添加父部门名称
      const deptData = dept.toJSON();
      deptData.parentName = parentName;
      
      // 记录查询结果
      logger.info(`部门查询成功: deptId=${deptId}, deptName=${dept.deptName}`);
      
      return deptData;
    } catch (error) {
      consoleLogger.error(`根据部门ID查询信息失败: ${error instanceof Error ? error.message : String(error)}`);
      return null;
    }
  }
  
  /**
   * 根据ID查询所有子部门
   * @param deptId 部门ID
   */
  async selectChildrenDeptById(deptId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`查询子部门: deptId=${deptId}`);
      
      const children = await Dept.findAll({
        where: {
          ancestors: { [Op.like]: `%,${deptId},%` }
        }
      });
      
      // 记录查询结果
      logger.info(`子部门查询完成: deptId=${deptId}, 子部门数量=${children.length}`);
      
      return children;
    } catch (error) {
      consoleLogger.error(`查询子部门失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询子部门失败');
    }
  }
  
  /**
   * 根据ID查询所有子部门（正常状态）
   * @param deptId 部门ID
   */
  async selectNormalChildrenDeptById(deptId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`查询正常状态子部门: deptId=${deptId}`);
      
      const count = await Dept.count({
        where: {
          status: '0',
          delFlag: '0',
          ancestors: { [Op.like]: `%,${deptId},%` }
        }
      });
      
      // 记录查询结果
      logger.info(`正常状态子部门查询完成: deptId=${deptId}, 子部门数量=${count}`);
      
      return count;
    } catch (error) {
      consoleLogger.error(`查询正常状态子部门失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询正常状态子部门失败');
    }
  }
  
  /**
   * 是否存在子节点
   * @param deptId 部门ID
   */
  async hasChildByDeptId(deptId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`检查是否存在子部门: deptId=${deptId}`);
      
      const count = await Dept.count({
        where: {
          parentId: deptId,
          delFlag: '0'
        }
      });
      
      // 记录查询结果
      logger.info(`子部门检查完成: deptId=${deptId}, 存在子部门=${count > 0}`);
      
      return count > 0;
    } catch (error) {
      consoleLogger.error(`检查是否存在子部门失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('检查子部门失败');
    }
  }
  
  /**
   * 查询部门是否存在用户
   * @param deptId 部门ID
   */
  async checkDeptExistUser(deptId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`检查部门是否存在用户: deptId=${deptId}`);
      
      const count = await User.count({
        where: {
          deptId,
          delFlag: '0'
        }
      });
      
      // 记录查询结果
      logger.info(`部门用户检查完成: deptId=${deptId}, 存在用户=${count > 0}`);
      
      return count > 0;
    } catch (error) {
      consoleLogger.error(`检查部门是否存在用户失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('检查部门用户失败');
    }
  }
  
  /**
   * 校验部门名称是否唯一
   * @param deptName 部门名称
   * @param parentId 父部门ID
   * @param deptId 部门ID
   */
  async checkDeptNameUnique(deptName: string, parentId: number, deptId?: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`校验部门名称唯一性: deptName=${deptName}, parentId=${parentId}, deptId=${deptId || '未提供'}`);
      
      const where: any = {
        deptName,
        parentId,
        delFlag: '0'
      };
      
      if (deptId) {
        where.deptId = { [Op.ne]: deptId };
      }
      
      const dept = await Dept.findOne({ where });
      const isUnique = !dept;
      
      // 记录校验结果
      logger.info(`部门名称唯一性校验完成: deptName=${deptName}, parentId=${parentId}, 是否唯一=${isUnique}`);
      
      return isUnique;
    } catch (error) {
      consoleLogger.error(`校验部门名称唯一性失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('校验部门名称唯一性失败');
    }
  }
  
  /**
   * 校验部门是否有数据权限
   * @param deptId 部门ID
   * @param userId 当前用户ID
   */
  async checkDeptDataScope(deptId: number, userId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`校验部门数据权限: deptId=${deptId}, userId=${userId}`);
      
      // 如果是超级管理员，拥有所有数据权限
      if (await User.findOne({ where: { userId, userName: 'admin' } })) {
        logger.info(`超级管理员拥有所有数据权限: userId=${userId}`);
        return true;
      }
      
      // 查询用户关联的角色
      const user = await User.findByPk(userId, {
        include: [
          {
            model: Role,
            where: { delFlag: '0', status: '0' }
          }
        ]
      });
      
      if (!user) {
        logger.warn(`未找到用户或用户无角色: userId=${userId}`);
        return false;
      }
      
      const roles = user.get('Roles') as Role[];
      
      for (const role of roles) {
        // 全部数据权限
        if (role.dataScope === '1') {
          logger.info(`用户角色拥有全部数据权限: userId=${userId}, roleId=${role.roleId}`);
          return true;
        }
        
        // 自定义数据权限
        if (role.dataScope === '2') {
          const result = await RoleDept.findOne({
            where: {
              roleId: role.roleId,
              deptId
            }
          });
          if (result) {
            logger.info(`用户角色拥有自定义数据权限: userId=${userId}, roleId=${role.roleId}, deptId=${deptId}`);
            return true;
          }
        }
        
        // 部门数据权限
        if (role.dataScope === '3') {
          const dept = await Dept.findByPk(deptId);
          if (dept && user.deptId === dept.deptId) {
            logger.info(`用户角色拥有部门数据权限: userId=${userId}, roleId=${role.roleId}, deptId=${deptId}`);
            return true;
          }
        }
        
        // 部门及以下数据权限
        if (role.dataScope === '4') {
          const dept = await Dept.findByPk(deptId);
          if (dept && (
            // 本部门
            user.deptId === dept.deptId ||
            // 子部门
            (dept.ancestors && dept.ancestors.includes(`,${user.deptId},`))
          )) {
            logger.info(`用户角色拥有部门及以下数据权限: userId=${userId}, roleId=${role.roleId}, deptId=${deptId}`);
            return true;
          }
        }
        
        // 仅本人数据权限
        if (role.dataScope === '5') {
          // 本人创建的部门
          const dept = await Dept.findOne({
            where: {
              deptId,
              createBy: user.userName
            }
          });
          if (dept) {
            logger.info(`用户角色拥有仅本人数据权限: userId=${userId}, roleId=${role.roleId}, deptId=${deptId}`);
            return true;
          }
        }
      }
      
      logger.warn(`用户无权限访问部门: userId=${userId}, deptId=${deptId}`);
      return false;
    } catch (error) {
      consoleLogger.error(`校验部门数据权限失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('校验部门数据权限失败');
    }
  }
  
  /**
   * 新增保存部门信息
   * @param dept 部门信息
   */
  async insertDept(dept: any) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`新增部门: deptName=${dept.deptName}, parentId=${dept.parentId}`);
      
      // 设置祖级列表
      await this.setDeptAncestors(dept);
      
      const result = await Dept.create(dept);
      
      // 记录操作结果
      logger.info(`部门新增成功: deptId=${result.deptId}, deptName=${result.deptName}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`新增部门失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('新增部门失败');
    }
  }
  
  /**
   * 修改保存部门信息
   * @param dept 部门信息
   */
  async updateDept(dept: any) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`修改部门: deptId=${dept.deptId}, deptName=${dept.deptName}`);
      
      // 设置祖级列表
      await this.setDeptAncestors(dept);
      
      // 如果更新了父部门，要更新子部门的祖级列表
      if (dept.parentId !== undefined) {
        const oldDept = await Dept.findByPk(dept.deptId);
        if (oldDept && oldDept.parentId !== dept.parentId) {
          // 更新子部门的祖级列表
          await this.updateDeptChildren(dept.deptId, dept.ancestors || '');
        }
      }
      
      const result = await Dept.update(dept, {
        where: { deptId: dept.deptId }
      });
      
      // 记录操作结果
      logger.info(`部门修改完成: deptId=${dept.deptId}, 影响行数=${result[0]}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`修改部门失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('修改部门失败');
    }
  }
  
  /**
   * 设置部门的祖级列表
   * @param dept 部门信息
   */
  private async setDeptAncestors(dept: any) {
    try {
      logger.debug(`设置部门祖级列表: deptId=${dept.deptId || '新部门'}, parentId=${dept.parentId}`);
      
      if (dept.parentId && dept.parentId !== 0) {
        const parent = await Dept.findByPk(dept.parentId);
        if (parent) {
          // 设置祖级列表
          dept.ancestors = parent.ancestors ? `${parent.ancestors},${dept.parentId}` : `0,${dept.parentId}`;
        } else {
          dept.ancestors = `0,${dept.parentId}`;
        }
      } else {
        dept.ancestors = '0';
      }
      
      logger.debug(`部门祖级列表设置完成: ancestors=${dept.ancestors}`);
    } catch (error) {
      consoleLogger.error(`设置部门祖级列表失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('设置部门祖级列表失败');
    }
  }
  
  /**
   * 修改子元素关系
   * @param deptId 部门ID
   * @param ancestors 祖级列表
   */
  private async updateDeptChildren(deptId: number, ancestors: string) {
    try {
      logger.debug(`更新子部门祖级列表: deptId=${deptId}, ancestors=${ancestors}`);
      
      // 查询所有子部门
      const children = await Dept.findAll({
        where: {
          parentId: deptId,
          delFlag: '0'
        }
      });
      
      for (const child of children) {
        // 更新子部门的祖级列表
        const newAncestors = `${ancestors},${deptId}`;
        await Dept.update(
          { ancestors: newAncestors },
          { where: { deptId: child.deptId } }
        );
        
        // 递归更新子部门的子部门
        await this.updateDeptChildren(child.deptId, newAncestors);
      }
      
      logger.debug(`子部门祖级列表更新完成: deptId=${deptId}, 子部门数量=${children.length}`);
    } catch (error) {
      consoleLogger.error(`更新子部门祖级列表失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('更新子部门祖级列表失败');
    }
  }
  
  /**
   * 删除部门管理信息
   * @param deptId 部门ID
   */
  async deleteDeptById(deptId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`删除部门: deptId=${deptId}`);
      
      const result = await Dept.update(
        { delFlag: '2' },
        { where: { deptId } }
      );
      
      // 记录操作结果
      logger.info(`部门删除完成: deptId=${deptId}, 影响行数=${result[0]}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`删除部门失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('删除部门失败');
    }
  }
}

export default new DeptService(); 